package com.workingpub.commons.jdbc.config.internal;

import java.util.Hashtable;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import com.workingpub.commons.jdbc.SqlDefineContext;
import com.workingpub.commons.jdbc.binding.SqlDefineEntry;
import com.workingpub.commons.jdbc.binding.SqlMapping;

@Service("sqlDefineContext")
public class DefaultSqlDefineContext implements SqlDefineContext {
	private static final Logger logger = LoggerFactory.getLogger(DefaultSqlDefineContext.class);

	private static final Map<String, Map<String, SqlMapping>> Domain_SqlMappings;

	static {
		Domain_SqlMappings = new Hashtable<String, Map<String, SqlMapping>>();
	}

	@Override
	public void addSqlDefines(SqlDefineEntry sqlDefines) {
		if (null == sqlDefines) {
			return;
		}

		for (SqlMapping entry : sqlDefines.getSqlMappings()) {
			addSqlMapping(entry, sqlDefines.getDatabaseCode());
		}
	}

	@Override
	public void removeSqlDefines(SqlDefineEntry sqlDefines) {
		if (null == sqlDefines) {
			return;
		}

		for (SqlMapping entry : sqlDefines.getSqlMappings()) {
			removeSqlMapping(entry, sqlDefines.getDatabaseCode());
		}

	}

	private void removeSqlMapping(SqlMapping sqlMapping, String databaseCode) {
		String domainGroup = StringUtils.hasText(databaseCode) ? databaseCode : Default_Domain_Group;
		Assert.isTrue(StringUtils.hasText(sqlMapping.getId()), "The SqlMapping id can't is null or empty.");
		if (Domain_SqlMappings.containsKey(domainGroup)
				&& Domain_SqlMappings.get(domainGroup).containsKey(sqlMapping.getId())) {
			Domain_SqlMappings.get(domainGroup).remove(sqlMapping.getId());
			logger.info("Success to remove the SqlMapping : " + sqlMapping.getId());
		}
	}

	@Override
	public void addSqlMapping(SqlMapping sqlMapping, String databaseCode) {
		String domainGroup = StringUtils.hasText(databaseCode) ? databaseCode : Default_Domain_Group;
		Assert.isTrue(StringUtils.hasText(sqlMapping.getId()), "The SqlMapping id can't is null or empty.");

		if (!Domain_SqlMappings.containsKey(domainGroup)) {
			final Map<String, SqlMapping> sqlMappings = new Hashtable<String, SqlMapping>();
			Domain_SqlMappings.put(domainGroup, sqlMappings);
		}
		Domain_SqlMappings.get(domainGroup).put(sqlMapping.getId(), sqlMapping);

		logger.info("Success to put a SqlMapping : " + sqlMapping.getId());
	}

	@Override
	public void removeSqlMapping(String sqlId, String databaseCode) {
		if (!StringUtils.hasText(sqlId)) {
			return;
		}
		String domainGroup = StringUtils.hasText(databaseCode) ? databaseCode : Default_Domain_Group;
		if (Domain_SqlMappings.containsKey(domainGroup) && Domain_SqlMappings.get(domainGroup).containsKey(sqlId)) {
			Domain_SqlMappings.get(domainGroup).remove(sqlId);
		}
	}

	@Override
	public SqlMapping getSqlMapping(String sqlId) {
		return getSqlMapping(sqlId, Default_Domain_Group);
	}

	@Override
	public SqlMapping getSqlMapping(String sqlId, String domainCode) {
		if (!StringUtils.hasText(sqlId)) {
			return null;
		}

		String groupCode = StringUtils.hasText(domainCode) ? domainCode : Default_Domain_Group;
		Assert.isTrue(Domain_SqlMappings.get(groupCode).containsKey(sqlId),
				"SqlMapping is not exists, domain : " + groupCode + "\tsqlId : " + sqlId);
		return Domain_SqlMappings.get(groupCode).get(sqlId);
	}

	@Override
	public int getSqlMappingSize() {
		return getSqlMappingSize(Default_Domain_Group);
	}

	@Override
	public int getSqlMappingSize(String domainCode) {
		String groupCode = StringUtils.hasText(domainCode) ? domainCode : Default_Domain_Group;
		return Domain_SqlMappings.get(groupCode).size();
	}
}
